using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Mono.Unix.Native;
using System.Xml;

namespace Mehat.San.SanFS
{
	public class MockChangerVirtualMount : VirtualMount
	{
		private string	mExternalPath;
		private long cDiscChangeDelay = 40;
		private long cMaxReadRate = 21600000;
		
		
		
		public MockChangerVirtualMount()
		:  base()
		{
		}
		
		public MockChangerVirtualMount(XmlNode XmlConfig)
			: base(XmlConfig) 
		{
			mExternalPath = XmlConfig.FirstChild.Attributes.GetNamedItem("ExtPath").Value;
			
			Console.WriteLine("MockChangerVirtualMount.ctor(): ExtPath = '{0}'", mExternalPath);
		}

		public override IVirtualMount CreateInstance(XmlNode XmlConfig)
		{
			return new MockChangerVirtualMount(XmlConfig);
		}

		protected override void Attach(IDirectory InternalRoot)
		{
			AttachDirectory(mExternalPath, InternalRoot);
		}
		
		private void AttachDirectory(string ExternalPath, IDirectory InternalDir)
		{
			IntPtr	dir = Syscall.opendir(ExternalPath);
			Dirent	dent;
			
			while ((dent = Syscall.readdir(dir))!= null)
			{
				if (dent.d_name == "." || dent.d_name == "..")
					continue;
					
				if (dent.d_type == 4)  // DT_DIR
				{
					IDirectory	newDir;
					string		newExtPath = ExternalPath + "/" + dent.d_name;
					
					if ((newDir = (IDirectory) DirEntFactory.Lookup(InternalDir, dent.d_name, false)) != null)
					{
						/*
						 * Collision detected
						 */
						 
						 if (!Merge)
						 {
						 	/*
						 	 * Add a random suffix to the directoryname
						 	 */
						 	 Random	r = new Random();
						 	 int	suffix = r.Next(1, 1000);
						 	 string	newName = dent.d_name + suffix.ToString();
						 	 
						 	 Console.WriteLine("Warning: Collision on '{0}', appending random suffix '{1}'", dent.d_name, suffix);
						 	 try
						 	 {
						 	 	newDir = DirEntFactory.CreateDirectory(this, InternalDir, newName);
						 	 }
						 	 catch (Exception ex)
						 	 {
						 	 	Console.WriteLine("Error creating directory ({0})", ex.Message);
						 	 	throw;
						 	 }
						 	 
						 } else  // Merge == true
						 {
						 	Console.WriteLine("Collision detected on '{0}' but its okay! (merging)", dent.d_name);
						 }
					}
					else // No Collision
					{
						newDir = DirEntFactory.CreateDirectory(this, InternalDir, dent.d_name);
					}
					
					/*
					 * Recurse down subdirectories
					 */
					AttachDirectory(newExtPath, newDir);
				} else if (dent.d_type == 8) // DT_reg
				{
					DirEntFactory.CreateFile(this, InternalDir, ExternalPath + "/" + dent.d_name);
				}
				//Console.WriteLine("entry '{0}' is type {1}", dent.d_name, dent.d_type);
		
			}
			
		}
		
		public override void OpenFile(FileHandle Fh)
		{
			Fh.File.Open(Fh);
		}
		
		public override void FlushFile(FileHandle Fh)
		{
			Fh.File.Flush(Fh);
		}
		
		public override void ReleaseFile(FileHandle Fh)
		{
			Fh.File.Release(Fh);
		}
		
		public override long ReadFile(FileHandle Fh, byte []Buffer, long Offset)
		{
			return Fh.File.Read(Fh, Buffer, Offset);
		}
		
		public string ExternalPath
		{
			get { return mExternalPath; }
			set
			{
				mExternalPath = value;

				if (System.IO.Directory.Exists(mExternalPath))
					throw new ArgumentException("Path does not exist", "ExternalPath");
			}
		}
	}  // END CLASS
}  // END NAMESPACE
